package logic

import (
	"context"
	"errors"
	"gozero-microservices/gateway-api/define"
	"gozero-microservices/gateway-api/internal/breaker"
	"gozero-microservices/gateway-api/internal/svc"
	"gozero-microservices/gateway-api/internal/tools"
	"gozero-microservices/gateway-api/utils"
	"gozero-microservices/user-service/rpc/types/user"
	"strconv"
	"time"

	"github.com/google/uuid"
	"github.com/zeromicro/go-zero/core/logx"
)

/*
 +----------------------------------------------------------------------
 + Title        : UserLogic
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2025-08-08
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 用户逻辑
 +----------------------------------------------------------------------
*/

type UserLogic struct {
	BaseLogic
}

/**
 * 创建用户逻辑实例
 *
 * @param context.Context ctx ----------------------必传
 * @param *svc.ServiceContext svcCtx ---------------必传
 * @return *UserLogic
 * @author huwl
 * @date 2025/10/14 12:54:03
 */
func NewUserLogicInstance(ctx context.Context, svcCtx *svc.ServiceContext) *UserLogic {
	return &UserLogic{
		BaseLogic{
			Ctx:    ctx,
			SvcCtx: svcCtx,
			Logger: logx.WithContext(ctx),
		},
	}
}

/**
 * 注册
 *
 * @param map[string]interface{} params ------------必传
 * @return error
 * @author huwl
 * @date 2025/10/14 12:54:03
 */
func (logic *UserLogic) Register(params map[string]interface{}) error {
	// 远程调用用户服务之用户
	_, err := logic.SvcCtx.UserSrv.AddUser(logic.Ctx, &user.AddUserRequest{
		Username: params["username"].(string),
		Mobile:   params["mobile"].(string),
		Password: params["password"].(string),
		Status:   1,
	})
	if err != nil {
		return err
	}

	return nil
}

/**
 * 用户名登录
 *
 * @param map[string]interface{} params ------------必传
 * @return map[string]interface{}, error
 * @author huwl
 * @date 2025/10/14 12:54:03
 */
func (logic *UserLogic) Login(params map[string]interface{}) (map[string]interface{}, error) {
	// 远程调用用户服务之用户
	userResult, err := logic.SvcCtx.UserSrv.Row(logic.Ctx, &user.QueryUserRequest{
		Username: params["username"].(string),
		Status:   "1",
	})
	if err != nil {
		return nil, err
	}

	if !utils.CompareBcrypt(userResult.User.Password, params["password"].(string)) {
		return nil, errors.New("密码错误")
	}

	// 生成token
	token, err := utils.GenerateToken(userResult.User.Uid)
	if err != nil {
		return nil, err
	}

	// 生成refreshToken
	refreshToken := uuid.New().String()
	// 需要将refreshToken存入redis
	ri, err := tools.NewRedisInstance(logic.SvcCtx)
	if err != nil {
		return nil, err
	}
	err = ri.RedisSet("userRefreshToken:"+strconv.FormatInt(int64(userResult.User.Uid), 10), refreshToken, time.Hour*12*10)
	if err != nil {
		return nil, err
	}

	return map[string]interface{}{
		"user":              userResult.User,
		"token":             token,
		"token_expire_time": time.Now().Add(time.Duration(define.TokenExpireTime)).Unix(),
		"refresh_token":     refreshToken,
	}, nil
}

/**
 * 列表
 *
 * @param map[string]interface{} params ------------必传
 * @param uint32 page ------------------------------必传
 * @param int8 pageSize ----------------------------必传
 * @param string order -----------------------------必传
 * @retrue *user.UserListResponse, error
 * @author huwl
 */
func (logic *UserLogic) List(params *user.QueryUserRequest, page uint32, pageSize int8, order string) (*user.UserListResponse, error) {
	ulr, err := logic.SvcCtx.UserSrv.UserList(logic.Ctx, params)
	if err != nil {
		return nil, err
	}

	return ulr, nil
}

/**
 * 详情【带熔断和降级】
 *
 * @param uint64 uid -------------------------------必传
 * @retrue *user.User, error
 * @author huwl
 */
func (logic *UserLogic) Detail(uid uint) (*user.User, error) {
	brk := breaker.GetBreakerManager().GetServiceBreaker(breaker.UserService)

	var result *user.User
	var callErr error

	// 使用降级策略
	err := brk.DoWithFallback(func() error {
		// 远程调用用户服务之用户
		resp, err := logic.SvcCtx.UserSrv.UserDetail(logic.Ctx, &user.UserDetailRequest{})
		if err != nil {
			callErr = err
			return err
		}
		result = resp.User

		return nil
	}, func(err error) error {
		// 降级逻辑
		// 多种降级方案
		switch {
		case errors.Is(err, context.DeadlineExceeded): // 超时降级：返回默认用户信息
			result = &user.User{
				Uid:       1000,
				Username:  "xxx",
				Email:     "xxx@sina.com",
				AvatarUrl: "/default-avatar.png",
			}
		default: // 其他错误：尝试从缓存获取
			// 这里实现缓存逻辑，比如从 Redis 获取
			// 如果获取成功返回用户信息，否则返回错误

			// 缓存也没有，返回业务错误
			return errors.New("服务暂时不可用，请稍后重试")
		}

		return nil
	})
	if err != nil {
		return nil, err
	}
	if callErr != nil {
		return nil, callErr
	}

	return result, nil
}
